// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:build drangfly | | freebsd | linux | | netbsd | | | openbsd 

package runtime

import (
	"internal/abi"
	"unsafe"
)

func dumpregs(c *sigctxt) {
	print("trap    ", hex(c.trap()), "\n")
	print("error   ", hex(c.error()), "\n")
	print("oldmask ", hex(c.oldmask()), "\n")
	print("r0      ", hex(c.r0()), "\n")
	print("r1      ", hex(c.r1()), "\n")
	print("r2      ", hex(c.r2()), "\n")
	print("r3      ", hex(c.r3()), "\n")
	print("r4      ", hex(c.r4()), "\n")
	print("r5      ", hex(c.r5()), "\n")
	print("r6      ", hex(c.r6()), "\n")
	print("r7      ", hex(c.r7()), "\n")
	print("r8      ", hex(c.r8()), "\n")
	print("r9      ", hex(c.r9()), "\n")
	print("r10     ", hex(c.r10()), "\n")
	print("fp      ", hex(c.fp()), "\n")
	print("ip      ", hex(c.ip()), "\n")
	print("sp      ", hex(c.sp()), "\n")
	print("lr      ", hex(c.lr()), "\n")
	print("pc      ", hex(c.pc()), "\n")
	print("cpsr    ", hex(c.cpsr()), "\n")
	print("fault   ", hex(c.fault()), "\n")
}

// go:nosplit 
// go:nowritebarrierrec 
func (c *sigctxt) sigpc() uintptr { return uintptr(c.pc()) }

func (c *sigctxt) sigsp() uintptr { return uintptr(c.sp()) }
func (c *sigctxt) siglr() uintptr { return uintptr(c.lr()) }

// preparePanic设置堆栈，使其看起来像对Sigmanic的调用。
func (c *sigctxt) preparePanic(sig uint32, gp *g) {
	// 我们安排lr和pc来假装惊慌失措的
	// 函数直接调用SIGMANIC。
	// 始终将LR保存到堆栈中，以便正确处理leaf 
	// 函数中的恐慌。这粉碎了堆栈框架，但无论如何我们不会回到那里。
	sp := c.sp() - 4
	c.set_sp(sp)
	*(*uint32)(unsafe.Pointer(uintptr(sp))) = c.lr()

	pc := gp.sigpc

	if shouldPushSigpanic(gp, pc, uintptr(c.lr())) {
		// 让它看起来像一台叫做sigpanic的故障PC。
		c.set_lr(uint32(pc))
	}

	// 以防我们因为外部C代码而惊慌失措
	c.set_r10(uint32(uintptr(unsafe.Pointer(gp))))
	c.set_pc(uint32(abi.FuncPCABIInternal(sigpanic)))
}

func (c *sigctxt) pushCall(targetPC, resumePC uintptr) {
	// 将LR推到堆栈中，因为我们将对其进行重击，以便
	// 推送调用。被推送的函数负责
	// 恢复LR并设置SP。
	// gentraceback知道这个额外的插槽。
	sp := c.sp() - 4
	c.set_sp(sp)
	*(*uint32)(unsafe.Pointer(uintptr(sp))) = c.lr()
	// 设置PC和LR，以假装正在发送信号的函数
	// 在resumePC上调用targetPC。
	c.set_lr(uint32(resumePC))
	c.set_pc(uint32(targetPC))
}
